#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include "Bank.h"
#include "BankSupport.h"
#include "ndds/ndds_requestreply_cpp.h"

using namespace DDS;

/* Delete all entities */
static int service_shutdown(
    DomainParticipant *participant)
{
    ReturnCode_t retcode;
    int status = 0;

    if (participant != NULL) {
        retcode = participant->delete_contained_entities();
        if (retcode != RETCODE_OK) {
            printf("delete_contained_entities error %d\n", retcode);
            status = -1;
        }

        retcode = TheParticipantFactory->delete_participant(participant);
        if (retcode != RETCODE_OK) {
            printf("delete_participant error %d\n", retcode);
            status = -1;
        }
    }

    /* RTI Connext provides finalize_instance() method on
       domain participant factory for people who want to release memory used
       by the participant factory. Uncomment the following block of code for
       clean destruction of the singleton. */
/*
    retcode = DomainParticipantFactory::finalize_instance();
    if (retcode != RETCODE_OK) {
        printf("finalize_instance error %d\n", retcode);
        status = -1;
    }
*/

    return status;
}

extern "C" int service_main(int domainId, int sample_count)
{
    DomainParticipant *participant = NULL;
    //Publisher *publisher = NULL;
    //Topic *topic = NULL;
    //DataWriter *writer = NULL;
    //Bank::AddressDataWriter * Bank_Address_writer = NULL;
    Bank::Address *instance = NULL;
    //ReturnCode_t retcode;
    //InstanceHandle_t instance_handle = HANDLE_NIL;
    const char *type_name = NULL;
    int count = 0;  
    Duration_t period = {4,0};

    /* To customize participant QoS, use 
       the configuration file USER_QOS_PROFILES.xml */
    participant = TheParticipantFactory->create_participant(
        domainId, PARTICIPANT_QOS_DEFAULT, 
        NULL /* listener */, STATUS_MASK_NONE);
    if (participant == NULL) {
        printf("create_participant error\n");
        service_shutdown(participant);
        return -1;
    }

    connext::Replier<Bank::Account_balance_request,
		             Bank::Account_balance_reply> replier(participant, "BankAccount");
    /* Main loop */
    for(count=0; (sample_count == 0) || (count < sample_count);) 
    {
      connext::LoanedSamples<Bank::Account_balance_request> 
	requests = replier.receive_requests(period);

      for(connext::LoanedSamples<Bank::Account_balance_request>::iterator iter = requests.begin();
          iter != requests.end();
          ++iter)
      {
        Bank::Account_balance_reply reply;
        reply.result._d = 0;
        reply.result._u.balance._return = count*2;
        reply.request_id = iter->data().request_id;
        replier.send_reply(reply, iter->identity());
        ++count;
      }
        //NDDSUtility::sleep(period);
    }

/*
    retcode = Bank_Address_writer->unregister_instance(
        *instance, instance_handle);
    if (retcode != RETCODE_OK) {
        printf("unregister instance error %d\n", retcode);
    }
*/

    /* Delete all entities */
    return service_shutdown(participant);
}

int main(int argc, char *argv[])
{
    int domainId = 65;
    int sample_count = 0; /* infinite loop */

    if (argc >= 2) {
        domainId = atoi(argv[1]);
    }
    if (argc >= 3) {
        sample_count = atoi(argv[2]);
    }

    /* Uncomment this to turn on additional logging
    NDDSConfigLogger::get_instance()->
        set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, 
                                  NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL);
    */
    try {
      return service_main(domainId, sample_count);
    }
    catch(std::exception & ex)
    {
      std::cout << "Exception: " << ex.what() << std::endl;
    }
}

